﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Configuration;
using Microsoft.VisualStudio.Shell.Interop;

namespace PK2
{
    internal class PKPluginsController: IProcrastinationKit
    {
        [ImportMany(typeof(IPKPlugin))]
        private List<IPKPlugin> _plugins;
        private PKCompletionSet _completionSet;
        private PKCompletionSet _tokensCompletionSet;
        private PKCompletionSet _commandsCompletionSet;
    
        internal IList<IPKPlugin> Plugins
        {
            get { return _plugins; }
        }

        internal void Initialize()
        {
            this._plugins = new List<IPKPlugin>();

            //Loads components on runtime----------------------------------------
            AggregateCatalog cat = new AggregateCatalog();
            cat.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            cat.Catalogs.Add(new DirectoryCatalog(Path.Combine(path,"Plugins")));

            CompositionContainer contnr = new CompositionContainer(cat);
            contnr.ComposeParts(this);
            //--------------------------------------------------------------------

            foreach (IPKPlugin plugin in _plugins)
            {
                var cfg = ConfigurationManager.OpenExeConfiguration(plugin.GetType().Assembly.ManifestModule.FullyQualifiedName);

                plugin.Initialize(this, cfg);
            }
            BuildTokensCompletionSet();
            BuildCommandsCompletionSet();
        }

        public bool SetCompletionSetForChar(char typedChar)
        {
            _completionSet = typedChar == PKTokenConstants.InitToken ? _tokensCompletionSet :
                             typedChar == PKTokenConstants.CommandToken ? _commandsCompletionSet :
                             (from p in this.Plugins
                              from cs in p.CompletionSets
                              where cs.LaunchToken == typedChar
                              select cs).FirstOrDefault();

            return _completionSet != null;
        }

        public bool IsCharLaunchToken(char typedChar)
        {
            var res = ((from p in this.Plugins
                    from cs in p.CompletionSets
                    where cs.LaunchToken == typedChar
                    select true).FirstOrDefault());
            return typedChar == PKTokenConstants.InitToken ||
                   typedChar == PKTokenConstants.CommandToken ||
                   res;
        }

        private void BuildCommandsCompletionSet()
        {
            //TODO: check how to insert commands
            var plugin = _plugins.First(p => p.Token == "twitter");
            _commandsCompletionSet = new PKCompletionSet()
            {
                DisplayName = "Commands",
                LaunchToken = PKTokenConstants.CommandToken,
                Items = plugin.Commands.Select(i => new PKCompletionItem
                {
                    InsertionText = i.InsertionText,
                    DisplayText = i.DisplayText,
                    Description = i.Description
                }).ToArray()
            };
            
        }

        private void BuildTokensCompletionSet()
        {
            _tokensCompletionSet = new PKCompletionSet()
            {
                DisplayName = "PKTokens",
                LaunchToken = PKTokenConstants.InitToken,
                Items = _plugins.Select(i => new PKCompletionItem
                {
                    InsertionText = i.Token,
                    DisplayText = i.Token,
                    Description = i.Description
                }).ToArray()
            };
        }

        public PKCompletionSet GetCompletionSet()
        {
            return _completionSet;
        }

        internal IVsStatusbar StatusBar { get; set; }

        public void SetTextInTheStatusBar(string text)
        {
            StatusBar.SetText(text);
        }
    }
}
